﻿using HalconDotNet;
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;

namespace DetectApp.Display;

public class CircleControl : ROIControl
{
    private readonly Canvas _canvas;
    private readonly Ellipse _ellipse;
    private readonly List<Shape> _docEllipse = new();
    public double K { get => _canvas.ActualWidth / 500.0; }
    private int _docDiameter = 0;
    private double _initRadius = 50;
    private bool _isMove;
    private bool _isSCale1;
    private bool _isSCale2;
    private bool _isSCale3;
    private bool _isSCale4;
    private bool _isRotate;
    private Point _startPoint;
    private double _circleRad;
    private Point _circleCenter;
    private double _startTopLeft;
    private double _startTopUp;

    public CircleControl(Canvas canvas, Color color)
    {
        _canvas = canvas;
        _canvas.MouseMove += Canvas_MouseMove;
        _ellipse = new()
        {
            Width = _initRadius * K,
            Height = _initRadius * K,
            Fill = new SolidColorBrush(Colors.Red) { Opacity = 0.1 },
            Stroke = new SolidColorBrush(color),
            StrokeThickness = 0.1,
        };
        _ellipse.MouseEnter += (sender, e) =>
        {
            UpdateEllipse(_ellipse, canvas);
        };
        _ellipse.MouseLeftButtonDown += Ellipse_MouseLeftButtonDown;
        canvas.Children.Add(_ellipse);
        Canvas.SetLeft(_ellipse, canvas.ActualWidth / 2 - _initRadius * K / 2);
        Canvas.SetTop(_ellipse, canvas.ActualHeight / 2 - _initRadius * K / 2);
        ROIChange?.Invoke(this, EventArgs.Empty);
    }

    public CircleControl(Canvas canvas, ROIParam rOIParam)
    {
        _canvas = canvas;
        _canvas.MouseMove += Canvas_MouseMove;
        _ellipse = new()
        {
            Width = rOIParam.circle_width,
            Height = rOIParam.circle_height,
            Fill = new SolidColorBrush(Colors.Red) { Opacity = 0.1 },
            Stroke = new SolidColorBrush(Colors.Blue),
            StrokeThickness = 0.1,
        };
        _ellipse.MouseEnter += (sender, e) =>
        {
            UpdateEllipse(_ellipse, canvas);
        };
        _ellipse.MouseLeftButtonDown += Ellipse_MouseLeftButtonDown;
        canvas.Children.Add(_ellipse);
        Canvas.SetLeft(_ellipse, rOIParam.Left);
        Canvas.SetTop(_ellipse, rOIParam.Top);
        ROIChange?.Invoke(this, EventArgs.Empty);
    }

    private void Ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        _isMove = true;
        _startPoint = Mouse.GetPosition(_canvas);
        _startTopUp = Canvas.GetTop(_ellipse);
        _startTopLeft = Canvas.GetLeft(_ellipse);
    }

    private void Canvas_MouseMove(object sender, MouseEventArgs e)
    {
        if (Mouse.LeftButton == MouseButtonState.Released)
        {
            _isMove = false; _isSCale1 = false; _isSCale2 = false; _isSCale3 = false; _isSCale4 = false; _isRotate = false;
        }
        if (!_isSCale1 & !_isSCale2 & !_isSCale3 & !_isSCale4 & !_isMove & !_isRotate)
        {
            bool isClear = true;
            if (_ellipse.IsMouseOver == true) { isClear = false; }
            foreach (var rect in _docEllipse)
            {
                if (rect.IsMouseOver)
                {
                    isClear = false;
                    break;
                }
            }
            if (isClear)
            {
                _docEllipse.ForEach(e => { _canvas.Children.Remove(e); });
                _docEllipse.Clear();
            };
        }
        if (_isMove)
        {
            Point curPoint = Mouse.GetPosition(_canvas);
            var rPoint = curPoint - _startPoint;
            Canvas.SetLeft(_ellipse, _startTopLeft + rPoint.X);
            Canvas.SetTop(_ellipse, _startTopUp + rPoint.Y);
            UpdateEllipse(_ellipse, _canvas);
            ROIChange?.Invoke(this, EventArgs.Empty);
        }
        if (_isSCale1)
        {
            Point point = Mouse.GetPosition(_canvas);
            _ellipse.Width = (point.Y - _startPoint.Y) * 2 + _circleRad * 2;
            _ellipse.Height = (point.Y - _startPoint.Y) * 2 + _circleRad * 2;
            Canvas.SetLeft(_ellipse, -point.Y + _startPoint.Y + _circleCenter.X);
            Canvas.SetTop(_ellipse, -point.Y + _startPoint.Y + _circleCenter.Y);
            UpdateEllipse(_ellipse, _canvas);
            ROIChange?.Invoke(this, EventArgs.Empty);
        }
        if (_isSCale2)
        {
            Point point = Mouse.GetPosition(_canvas);
            _ellipse.Width = (-point.Y + _startPoint.Y) * 2 + _circleRad * 2;
            _ellipse.Height = (-point.Y + _startPoint.Y) * 2 + _circleRad * 2;
            Canvas.SetLeft(_ellipse, point.Y - _startPoint.Y + _circleCenter.X);
            Canvas.SetTop(_ellipse, point.Y - _startPoint.Y + _circleCenter.Y);
            UpdateEllipse(_ellipse, _canvas);
            ROIChange?.Invoke(this, EventArgs.Empty);
        }
        if (_isSCale3)
        {
            Point point = Mouse.GetPosition(_canvas);
            _ellipse.Width = (-point.X + _startPoint.X) * 2 + _circleRad * 2;
            _ellipse.Height = (-point.X + _startPoint.X) * 2 + _circleRad * 2;
            Canvas.SetLeft(_ellipse, point.X - _startPoint.X + _circleCenter.X);
            Canvas.SetTop(_ellipse, point.X - _startPoint.X + _circleCenter.Y);
            UpdateEllipse(_ellipse, _canvas);
            ROIChange?.Invoke(this, EventArgs.Empty);
        }
        if (_isSCale4)
        {
            Point point = Mouse.GetPosition(_canvas);
            _ellipse.Width = (point.X - _startPoint.X) * 2 + _circleRad * 2;
            _ellipse.Height = (point.X - _startPoint.X) * 2 + _circleRad * 2;
            Canvas.SetLeft(_ellipse, -point.X + _startPoint.X + _circleCenter.X);
            Canvas.SetTop(_ellipse, -point.X + _startPoint.X + _circleCenter.Y);
            UpdateEllipse(_ellipse, _canvas);
            ROIChange?.Invoke(this, EventArgs.Empty);
        }
    }

    private void UpdateEllipse(Ellipse ellipse, Canvas canvas)
    {
        //ROIChange?.Invoke(this, EventArgs.Empty);
        _docDiameter = (int)(5 * K);
        Brush fillBrush = new SolidColorBrush(Colors.Blue);
        double opacityK = 1;
        _docEllipse.ForEach(e => { canvas.Children.Remove(e); });
        _docEllipse.Clear();
        Point point = ellipse.TranslatePoint(new Point(ellipse.Width / 2, ellipse.Width), canvas);
        Ellipse circle1 = new() { Width = _docDiameter, Height = _docDiameter, Fill = fillBrush, Opacity = opacityK };
        Canvas.SetLeft(circle1, point.X - _docDiameter / 2);
        Canvas.SetTop(circle1, point.Y - _docDiameter / 2);
        canvas.Children.Add(circle1);
        _docEllipse.Add(circle1);
        circle1.MouseLeftButtonDown += (s, e) =>
        {
            _isSCale1 = true;
            _startPoint = Mouse.GetPosition(canvas);
            _circleRad = ellipse.Width / 2;
            _circleCenter.X = Canvas.GetLeft(ellipse);
            _circleCenter.Y = Canvas.GetTop(ellipse);
        };
        circle1.MouseLeftButtonUp += (s, e) => { _isSCale1 = false; };

        point = ellipse.TranslatePoint(new Point(ellipse.Width / 2, 0), canvas);
        Ellipse circle2 = new() { Width = _docDiameter, Height = _docDiameter, Fill = fillBrush, Opacity = opacityK };
        Canvas.SetLeft(circle2, point.X - _docDiameter / 2);
        Canvas.SetTop(circle2, point.Y - _docDiameter / 2);
        canvas.Children.Add(circle2);
        _docEllipse.Add(circle2);
        circle2.MouseLeftButtonDown += (s, e) =>
        {
            _isSCale2 = true;
            _startPoint = Mouse.GetPosition(canvas);
            _circleRad = ellipse.Width / 2;
            _circleCenter.X = Canvas.GetLeft(ellipse);
            _circleCenter.Y = Canvas.GetTop(ellipse);
        };
        circle2.MouseLeftButtonUp += (s, e) => { _isSCale2 = false; };

        point = ellipse.TranslatePoint(new Point(0, ellipse.Height / 2), canvas);
        Ellipse circle3 = new() { Width = _docDiameter, Height = _docDiameter, Fill = fillBrush, Opacity = opacityK };
        Canvas.SetLeft(circle3, point.X - _docDiameter / 2);
        Canvas.SetTop(circle3, point.Y - _docDiameter / 2);
        canvas.Children.Add(circle3);
        _docEllipse.Add(circle3);
        circle3.MouseLeftButtonDown += (s, e) =>
        {
            _isSCale3 = true;
            _startPoint = Mouse.GetPosition(canvas);
            _circleRad = ellipse.Width / 2;
            _circleCenter.X = Canvas.GetLeft(ellipse);
            _circleCenter.Y = Canvas.GetTop(ellipse);
        };
        circle3.MouseLeftButtonUp += (s, e) => { _isSCale3 = false; };

        point = ellipse.TranslatePoint(new Point(ellipse.Width, ellipse.Height / 2), canvas);
        Ellipse circle4 = new() { Width = _docDiameter, Height = _docDiameter, Fill = fillBrush, Opacity = opacityK };
        Canvas.SetLeft(circle4, point.X - _docDiameter / 2);
        Canvas.SetTop(circle4, point.Y - _docDiameter / 2);
        canvas.Children.Add(circle4);
        _docEllipse.Add(circle4);
        circle4.MouseLeftButtonDown += (s, e) =>
        {
            _isSCale4 = true;
            _startPoint = Mouse.GetPosition(canvas);
            _circleRad = ellipse.Width / 2;
            _circleCenter.X = Canvas.GetLeft(ellipse);
            _circleCenter.Y = Canvas.GetTop(ellipse);
        };
        circle4.MouseLeftButtonUp += (s, e) => { _isSCale4 = false; };
    }

    public override HRegion? GetRegion()
    {
        Point point = _ellipse.TranslatePoint(new Point { X = _ellipse.Width / 2, Y = _ellipse.Height / 2 }, _canvas);
        return new HRegion(point.Y, point.X, _ellipse.ActualWidth / 2);
    }

    public override ROIInfo GetROI()
    {
        ROIInfo roi = new ROIInfo();
        roi.ROIType = ROIType.圆;
        roi.Radius = _ellipse.ActualWidth / 2;
        Point point = _ellipse.TranslatePoint(new Point { X = _ellipse.Width / 2, Y = _ellipse.Height / 2 }, _canvas);
        roi.CircleX = point.X;
        roi.CircleY = point.Y;
        return roi;
    }

    public override ROIParam GetParam()
    {
        ROIParam roi = new() { ROIType = ROIType.圆 };
        roi.circle_width = _ellipse.ActualWidth;
        roi.circle_height = _ellipse.ActualHeight;
        roi.Left = Canvas.GetLeft(_ellipse);
        roi.Top = Canvas.GetTop(_ellipse);
        return roi;
    }

    public override void Remove()
    {
        _canvas.Children.Remove(_ellipse);
    }
}